//
//  Set.hpp
//  C3W_Demo_By_Fan
//
//  Created by 范静涛 on 2024/7/22.
//

//------------------------------------------------------------------------------
//【文件名】Set.hpp
//【功能模块和目的】集合类模版（元素不可重复的容器），声明与实现
//【开发者及日期】范静涛 2024/7/22
//【更改记录】
//------------------------------------------------------------------------------

#ifndef Set_hpp
#define Set_hpp

//size_t所属头文件
#include <cstddef>
//std异常基类所属头文件
#include <stdexcept>
//std::string字符串类所属头文件
#include <string>
//std::find函数所属头文件
#include <algorithm>
//DynamicContainer类模版所属头文件
#include "DynamicContainer.hpp"

//------------------------------------------------------------------------------
//【类模版名】Set
//【功能】元素不可重复的集合
//【接口说明】
//    默认构造函数
//    带参数构造函数
//    拷贝构造函数
//    赋值运算符overload
//    虚析构函数（可能做基类）
//    交集的赋值运算符overload(从概念出发，因存在的对象行为)
//    并集的赋值运算符overload(从概念出发，因存在的对象行为)
//    补集的赋值运算符overload(从概念出发，因存在的对象行为)
//    添加非重复元素(从概念出发，因存在的对象行为)
//    删除已存在元素(从概念出发，因存在的对象行为)
//    修改已存在元素为未存在元素值(从概念出发，因存在的对象行为)
//    清空集合(从概念出发，因存在的对象行为)
//    返回元素值的下标运算符overload(从概念出发，因存在的对象行为)
//    交集的运算符overload(从概念出发，因存在的对象行为)
//    并集的运算符overload(从概念出发，因存在的对象行为)
//    补集的运算符overload(从概念出发，因存在的对象行为)
//    判断是否存在指定元素(从概念出发，因存在的对象行为)
//    判断集合是否为空(从概念出发，因存在的对象行为)
//    允许集合最大容量MAX_COUNT(从概念出发，应存在的类属性)
//    当前集合最大容量MaxCount(从概念出发，应存在的意对象属性)
//    当前集合容量Count(从概念出发，应存在的对象行为)
//【开发者及日期】 范静涛 2024/7/22
//【更改记录】
//------------------------------------------------------------------------------
template<class T>
class Set{
public:
    //--------------------------------------------------------------------------
    //内嵌异常类
    //--------------------------------------------------------------------------
    //集合最大元素个数为0，需抛出此异常
    class MAX_COUNT_IS_ZERO : public std::invalid_argument{
    public:
        MAX_COUNT_IS_ZERO(): std::invalid_argument(
            std::string("Zero can't be used as set's max count")){
        }
    };
    //--------------------------------------------------------------------------

    //集合已满，无法添加新元素，需抛出此异常
    class IS_FULL : std::out_of_range{
    public:
        IS_FULL(size_t Max): std::out_of_range(
              std::string("Set is full with max count: ")
            + std::to_string(Max)){
        }
    };
    //--------------------------------------------------------------------------

    //删除并不存在的元素，需抛出此异常
    class NO_SUCH_ELEMENT : std::invalid_argument{
    public:
        NO_SUCH_ELEMENT(): std::invalid_argument(
            std::string("There is no such element in the set")){
        }
    };
    //--------------------------------------------------------------------------

    //加入已存在的元素，需抛出此异常
    class DUPLICATE_ELEMENT : std::invalid_argument{
    public:
        DUPLICATE_ELEMENT():std::invalid_argument(
            std::string("There is a duplicate element in the set")){
        }
    };
    
    //--------------------------------------------------------------------------
    //必要的构造、析构、赋值行为
    //--------------------------------------------------------------------------
    //默认构造函数
    Set(size_t MaxCount = MAX_COUNT);
    //带参数构造函数
    Set(const std::vector<T>& Source);
    //拷贝构造函数
    Set(const Set& Source);
    //赋值运算符overload
    Set& operator=(const Set& Source);
    //虚析构函数（可能做基类），无动态构造成员，默认实现
    virtual ~Set() = default;
    //--------------------------------------------------------------------------
    //非静态Setter成员函数
    //--------------------------------------------------------------------------
    //交集(同时在两个集合中的元素构成的集合)，&=赋值运算符overload
    Set& operator&=(const Set& ASet);
    //并集(存在任一集合中的元素构成的集合)，|=赋值运算符overload
    Set& operator|=(const Set& ASet);
    //并集(存在任一集合中的元素构成的集合)，+=赋值运算符overload
    Set& operator+=(const Set& ASet);
    //补集(在A集合但不在B集合的元素构成的集合)，^=赋值运算符overload
    Set& operator^=(const Set& ASet);
    //补集(在A集合但不在B集合的元素构成的集合)，-=赋值运算符overload
    Set& operator-=(const Set& ASet);
    //添加元素到集合，元素已存在则抛出异常
    void Append(const T& Element);
    //从集合中移除指定元素，元素出存在则抛出异常
    void Remove(const T& Element);
    //修改指定集合中指定元素为新元素，新元素已存在则抛出异常
    void Modify(const T& From, const T& To);
    //清空
    void Clear();
    //--------------------------------------------------------------------------
    //非静态Getter成员函数：需检查所有Getter是否有后置const
    //--------------------------------------------------------------------------
    //返回指定位置元素值的下标运算符overload
    T operator[](size_t Index) const;
    //判断集合相等运算符overload
    bool operator==(const Set& ASet) const;
    //判断集合不等运算符overload
    bool operator!=(const Set& ASet) const;
    //交集(同时在两个集合中的元素构成的集合)，&运算符overload
    Set operator&(const Set& ASet) const;
    //并集(存在任一集合中的元素构成的集合)，|运算符overload
    Set operator|(const Set& ASet) const;
    //并集(存在任一集合中的元素构成的集合)，+运算符overload
    Set operator+(const Set& ASet) const;
    //补集(在A集合但不在B集合的元素构成的集合)，^运算符overload
    Set operator^(const Set& ASet) const;
    //补集(在A集合但不在B集合的元素构成的集合)，-运算符overload
    Set operator-(const Set& ASet) const;
    //判断集合中存在指定元素
    bool Exists(const T& Element) const;
    //判断集合为空
    bool IsEmpty() const;
    //--------------------------------------------------------------------------
    //静态Getter数据成员
    //--------------------------------------------------------------------------
    //允许的集合元素个数上限
    static constexpr size_t MAX_COUNT{0xFFFFFFFFFFFFFFFE};
private:
    //--------------------------------------------------------------------------
    //私有 非静态数据成员
    //--------------------------------------------------------------------------
    //当前集合元素个数上限
    size_t m_MaxCount;
    //实际元素存储
    DynamicContainer<T> m_Elements;
public:
    //--------------------------------------------------------------------------
    //非静态常引用Getter数据成员
    //--------------------------------------------------------------------------
    //当前集合元素个数
    const size_t& Count{m_Elements.Count};
    //当前集合元素个数上限
    const size_t& MaxCount{m_MaxCount};
    //实际元素存储
    const DynamicContainer<T>& Elements{m_Elements};
};

//------------------------------------------------------------------------------
//必要的构造、析构、赋值行为
//------------------------------------------------------------------------------

//函数名：Set
//功能：默认构造函数，m_Elements初始化为空，MaxCount为0，则抛出异常
//入口参数：size_t MaxCount默认值为MAX_COUNT
//出口参数：无
//返回值：无
template<class T>
Set<T>::Set(size_t MaxCount) 
: m_Elements{std::vector<T>{}}, m_MaxCount(MaxCount){
    //MaxCount为0，则抛出异常
    if (m_MaxCount == 0) {
        throw MAX_COUNT_IS_ZERO();
    }
}
//------------------------------------------------------------------------------

//函数名：Set
//功能：带参数构造函数，参数指定的非重复元素个数为MaxCount
//     参数为空vector，则抛出异常
//入口参数：const std::vector<T>& Source
//出口参数：无
//返回值：无
template<class T>
Set<T>::Set(const std::vector<T>& Source) 
: m_Elements{std::vector<T>()}, m_MaxCount(Source.size()){
    //m_MaxCount为0(Source中无元素)，则抛出异常
    if (m_MaxCount == 0) {
        throw MAX_COUNT_IS_ZERO();
    }
    //逐一添加非重复元素
    for (auto e : Source) {
        if (!m_Elements.Exists(e)) {
            m_Elements.Append(e);
        }
    }
    //更新m_MaxCount
    m_MaxCount = m_Elements.Count;
    //m_MaxCount为0(Source中无元素)，则抛出异常
    if (MaxCount == 0) {
        throw MAX_COUNT_IS_ZERO();
    }
}
//------------------------------------------------------------------------------

//函数名：Set
//功能：拷贝构造函数，以参数初始化m_MaxCount和m_Elements
//入口参数：const Set<T>& Source
//出口参数：无
//返回值：无
template<class T>
Set<T>::Set(const Set<T>& Source)
: m_Elements{Source.m_Elements}, m_MaxCount(Source.MaxCount){
}
//------------------------------------------------------------------------------

//函数名：operator=
//功能：赋值运算符overload
//入口参数：const Set<T>& Source
//出口参数：无
//返回值：集合自身的引用
template<class T>
Set<T>& Set<T>::operator=(const Set& Source){
    if (this != &Source) {
        m_Elements = Source.m_Elements;
        m_MaxCount = Source.MaxCount;
    }
    return *this;
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//非静态Setter成员函数
//------------------------------------------------------------------------------

//函数名：operator&=
//功能：交集(同时在两个集合中的元素构成的集合)，&=赋值运算符overload
//入口参数：const Set<T>& Source
//出口参数：无
//返回值：集合自身的引用
template<class T>
Set<T>& Set<T>::operator&=(const Set<T>& ASet){
    //构造动态容器临时对象Temp
    DynamicContainer<T> Temp;
    //遍历ASet
    for (auto e : ASet.m_Elements) {
        //同时存在于自身集合和ASet，添加到Temp
        if (m_Elements.Exists(e)) {
            Temp.Append(e);
        }
    }
    //Temp赋值给自身元素动态容器
    m_Elements = Temp;
    return *this;
}
//------------------------------------------------------------------------------

//函数名：operator|=
//功能：并集(存在任一集合中的元素构成的集合)，|=赋值运算符overload
//入口参数：const Set<T>& Source
//出口参数：无
//返回值：集合自身的引用
template<class T>
Set<T>& Set<T>::operator|=(const Set<T>& ASet){
    //遍历ASet
    for (auto e : ASet.m_Elements) {
        //不在自身集合，添加
        if (!m_Elements.Exists(e)) {
            m_Elements.Append(e);
        }
    }
    return *this;
}
//------------------------------------------------------------------------------

//函数名：operator+=
//功能：并集(存在任一集合中的元素构成的集合)，+=赋值运算符overload
//入口参数：const Set<T>& Source
//出口参数：无
//返回值：集合自身的引用
template<class T>
Set<T>& Set<T>::operator+=(const Set<T>& ASet){
    return operator|=(ASet);
}
//------------------------------------------------------------------------------

//函数名：operator^=
//功能：补集(在A集合但不在B集合的元素构成的集合)，^=赋值运算符overload
//入口参数：const Set<T>& Source
//出口参数：无
//返回值：集合自身的引用
template<class T>
Set<T>& Set<T>::operator^=(const Set<T>& ASet){
    //构造动态容器临时对象Temp
    DynamicContainer<T> Temp;
    //遍历自身集合
    for (auto e : m_Elements) {
        //不在ASet中，添加到Temp
        if (!ASet.m_Elements.Exists(e)) {
            Temp.Append(e);
        }
    }
    //Temp赋值给自身元素动态容器
    m_Elements = Temp;
    return *this;
}
//------------------------------------------------------------------------------

//函数名：operator-=
//功能：补集(在A集合但不在B集合的元素构成的集合)，-=赋值运算符overload
//入口参数：const Set<T>& Source
//出口参数：无
//返回值：集合自身的引用
template<class T>
Set<T>& Set<T>::operator-=(const Set<T>& ASet){
    return operator&=(ASet);
}
//------------------------------------------------------------------------------

//函数名：Append
//添加元素到集合，如元素已存或集合已满，在则抛出异常
//入口参数：const T& Element
//出口参数：无
//返回值：无
template<class T>
void Set<T>::Append(const T& Element){
    //集合已满，抛出异常
    if (m_Elements.Count == m_MaxCount) {
        throw IS_FULL(m_MaxCount);
    }
    //元素已存在，抛出异常
    else if (m_Elements.Exists(Element)) {
        throw DUPLICATE_ELEMENT();
    }
    //添加新元素
    else{
        m_Elements.Append(Element);
    }
}
//------------------------------------------------------------------------------

//函数名：Remove
//功能：从集合中移除指定元素，如元素不存在，则抛出异常
//入口参数：const T& Element
//出口参数：无
//返回值：无
template<class T>
void Set<T>::Remove(const T& Element){
    //循环搜索比对
    for (size_t i = 0; i < Count; i++) {
        //找到指定元素，移除，返回
        if (m_Elements[i] == Element) {
            m_Elements.RemoveAT(i);
            return;
        }
    }
    //抛出异常
    throw NO_SUCH_ELEMENT();
}
//------------------------------------------------------------------------------

//函数名：Modify
//修改指定集合中指定元素为新元素值，如From不存在或To已存在，则抛出异常
//入口参数：const T& From, const T& To
//出口参数：无
//返回值：无
template<class T>
void Set<T>::Modify(const T& From, const T& To){
    //To已存在，抛出异常
    if (m_Elements.Exists(To)) {
        throw DUPLICATE_ELEMENT();
    }
    //循环搜索比对
    for (size_t i = 0; i < Count; i++) {
        //找到指定元素，赋值，返回
        if (m_Elements[i] == From) {
            m_Elements[i] = To;
            return;
        }
    }
    //From不存在，抛出异常
    throw NO_SUCH_ELEMENT();
}
//------------------------------------------------------------------------------

//函数名：Clear
//功能：清空，不修改m_MaxCount
//入口参数：无
//出口参数：无
//返回值：无
template<class T>
void Set<T>::Clear(){
    m_Elements.Clear();
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//非静态Getter成员函数：需检查所有Getter是否有后置const
//------------------------------------------------------------------------------

//函数名：operator[] const
//功能：返回指定位置元素值的下标运算符overload，越界访问又m_Elements的下标访问运算符出抛异常
//入口参数：size_t Index
//出口参数：无
//返回值：指定位置元素值
template<class T>
T Set<T>::operator[](size_t Index) const{
    return m_Elements[Index];
}
//------------------------------------------------------------------------------

//函数名：operator== const
//功能：判断集合相等运算符overload
//入口参数：const Set& ASet
//出口参数：无
//返回值：元素个数和不论顺序的全部元素相等，返回true，否在返回false
template<class T>
bool Set<T>::operator==(const Set& ASet) const{
    //元素个数不同，返回false
    if (Count != ASet.Count) {
        return false;
    }
    
    //某一元素不在另一集合中，返回false
    for (size_t i = 0; i < m_Elements.Count; i++) {
        if (ASet.Elements.Exists(m_Elements[i])) {
            return false;
        }
    }
    
    //元素个数和不论顺序的全部元素相等，返回true
    return true;
}
//------------------------------------------------------------------------------

//函数名：operator!= const
//功能：判断集合不等运算符overload
//入口参数：const Set& ASet
//出口参数：无
//返回值：元素个数或存在不重叠元素，返回true，否在返回false
template<class T>
bool Set<T>::operator!=(const Set& ASet) const{
    return !(*this == ASet);
}
//------------------------------------------------------------------------------

//函数名：operator& const
//功能：交集(同时在两个集合中的元素构成的集合)，&运算符overload
//入口参数：const Set<T>& Source
//出口参数：无
//返回值：结果集合
template<class T>
Set<T> Set<T>::operator&(const Set<T>& ASet) const{
    Set<T> Res{*this};
    return Res &= ASet;
}
//------------------------------------------------------------------------------

//函数名：operator| const
//功能：并集(存在任一集合中的元素构成的集合)，|运算符overload
//入口参数：const Set<T>& Source
//出口参数：无
//返回值：结果集合
template<class T>
Set<T> Set<T>::operator|(const Set<T>& ASet) const{
    Set<T> Res{*this};
    return Res |= ASet;
}
//------------------------------------------------------------------------------

//函数名：operator+ const
//功能：并集(存在任一集合中的元素构成的集合)，+运算符overload
//入口参数：const Set<T>& Source
//出口参数：无
//返回值：结果集合
template<class T>
Set<T> Set<T>::operator+(const Set<T>& ASet) const{
    return operator|(ASet);
}
//------------------------------------------------------------------------------

//函数名：operator^ const
//功能：补集(在A集合但不在B集合的元素构成的集合)，^运算符overload
//入口参数：const Set<T>& Source
//出口参数：无
//返回值：结果集合
template<class T>
Set<T> Set<T>::operator^(const Set<T>& ASet) const{
    Set<T> Res{*this};
    return Res ^= ASet;
}
//------------------------------------------------------------------------------

//函数名：operator- const
//功能：补集(在A集合但不在B集合的元素构成的集合)，-运算符overload
//入口参数：const Set<T>& Source
//出口参数：无
//返回值：结果集合
template<class T>
Set<T> Set<T>::operator-(const Set<T>& ASet) const{
    return operator^(ASet);
}
//------------------------------------------------------------------------------

//函数名：Exists const
//功能判断集合中存在指定元素
//入口参数：const T& Element
//出口参数：无
//返回值：存在返回true，否在返回false
template<class T>
bool Set<T>::Exists(const T& Element) const{
    return m_Elements.Exists(Element);
}
//------------------------------------------------------------------------------

//函数名：IsEmpty const
//功能：判断集合为空
//入口参数：无
//出口参数：无
//返回值：集合为空返回true，否在返回false
template<class T>
bool Set<T>::IsEmpty() const{
    return m_Elements.Count == 0;
}
//------------------------------------------------------------------------------

#endif /* Set_hpp */
